Support post render callback
[platform/core/uifw/pepper-dali.git] / pepper-dali / internal / output-impl.cpp
1 /*
2  * Copyright (c) 2016 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 <pepper-dali/internal/output-impl.h>
20
21 // INTERNAL INCLUDES
22 #include <pepper-dali/internal/compositor-impl.h>
23
24 // EXTERNAL INCLUDES
25 #include <dali/integration-api/adaptors/adaptor.h>
26 #include <dali/devel-api/adaptor-framework/render-surface.h>
27 #include <dali/integration-api/debug.h>
28
29 namespace Dali
30 {
31
32 namespace Pepper
33 {
34
35 namespace Internal
36 {
37
38 namespace
39 {
40
41 #if defined(DEBUG_ENABLED)
42 Integration::Log::Filter* gPepperOutputLogging  = Integration::Log::Filter::New( Debug::Verbose, false, "LOG_PEPPER_OUTPUT" );
43 #endif
44
45 static const struct pepper_output_backend outputInterface =
46 {
47   Output::OnDestroy,
48
49   Output::OnGetSubpixelOrder,
50   Output::OnGetMakerName,
51   Output::OnGetModelName,
52
53   Output::OnGetModeCount,
54   Output::OnGetMode,
55   Output::OnSetMode,
56
57   Output::OnAssignPlanes,
58   Output::OnStartRepaintLoop,
59   Output::OnRepaint,
60   Output::OnAttachSurface,
61   Output::OnFlushSurface
62 };
63
64 } // unnamed namespace
65
66 OutputPtr Output::New( Pepper::Compositor compositor, Application application, Pepper::Input input )
67 {
68   OutputPtr impl = new Output();
69
70   // Second-phase init of the implementation
71   impl->Initialize( compositor, application, input );
72
73   return impl;
74 }
75
76 Output::Output()
77 : mSize(),
78   mOutput( NULL ),
79   mPrimaryPlane( NULL ),
80   mRepaintRequest( false )
81 {
82 }
83
84 Output::~Output()
85 {
86 }
87
88 void Output::Initialize( Pepper::Compositor& compositor, Application application, Pepper::Input input )
89 {
90   mCompositor = compositor;
91   mInput = input;
92
93   RenderSurface& surface = Adaptor::Get().GetSurface();
94   PositionSize positionSize = surface.GetPositionSize();
95
96   mSize.width = positionSize.width;
97   mSize.height = positionSize.height;
98
99   mOutput = pepper_compositor_add_output( static_cast< pepper_compositor_t* >( Pepper::GetImplementation( compositor ).GetCompositorHandle() ), &outputInterface, "dali", this, WL_OUTPUT_TRANSFORM_NORMAL, 1 );
100   if( !mOutput )
101   {
102     DALI_LOG_INFO( gPepperOutputLogging, Debug::General, "Output::Initialize: pepper_compositor_add_output is failed\n" );
103     return;
104   }
105
106   mPrimaryPlane = pepper_output_add_plane( mOutput, NULL );
107   if( !mPrimaryPlane )
108   {
109     DALI_LOG_INFO( gPepperOutputLogging, Debug::General, "Output::Initialize: pepper_output_add_plane is failed\n" );
110     pepper_output_destroy( mOutput );
111     return;
112   }
113
114   application.ResizeSignal().Connect( this, &Output::OnResize );
115
116   // Set the thread-synchronization interface on the render-surface
117   surface.SetThreadSynchronization( *this );
118
119   DALI_LOG_INFO( gPepperOutputLogging, Debug::Verbose, "Output::Initialize: success [width = %.2f height = %.2f]\n", mSize.width, mSize.height );
120 }
121
122 void Output::OnDestroy( void* data )
123 {
124   Output* output = static_cast< Output* >( data );
125
126   if( output->mPrimaryPlane )
127   {
128     pepper_plane_destroy( output->mPrimaryPlane );
129     output->mPrimaryPlane = NULL;
130   }
131 }
132
133 int32_t Output::OnGetSubpixelOrder( void* data )
134 {
135   return WL_OUTPUT_SUBPIXEL_UNKNOWN;
136 }
137
138 const char* Output::OnGetMakerName( void* data )
139 {
140   return "PePPer DALi";
141 }
142
143 const char* Output::OnGetModelName( void* data )
144 {
145   return "PePPer DALi";
146 }
147
148 int Output::OnGetModeCount( void* data )
149 {
150   return 1;
151 }
152
153 void Output::OnGetMode( void* data, int index, pepper_output_mode_t* mode )
154 {
155   Output* output = static_cast< Output* >( data );
156
157   if( index != 0 )
158   {
159     DALI_LOG_INFO( gPepperOutputLogging, Debug::General, "Output::OnGetMode: wrong index [%d]\n", index );
160     return;
161   }
162
163   if( mode )
164   {
165     mode->flags = WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
166     mode->w = (int32_t)output->mSize.width;
167     mode->h = (int32_t)output->mSize.height;
168     mode->refresh = 60000;
169   }
170 }
171
172 pepper_bool_t Output::OnSetMode( void* data, const pepper_output_mode_t* mode )
173 {
174   return PEPPER_FALSE;
175 }
176
177 void Output::OnAssignPlanes( void* data, const pepper_list_t* viewList )
178 {
179   Output* output = static_cast< Output* >( data );
180   pepper_list_t* list;
181
182   pepper_list_for_each_list( list, viewList )
183   {
184     pepper_view_t* view = static_cast< pepper_view_t* >( list->item );
185     pepper_view_assign_plane( view, output->mOutput, output->mPrimaryPlane );
186   }
187 }
188
189 void Output::OnStartRepaintLoop( void* data )
190 {
191   Output* output = static_cast< Output* >( data );
192   struct timespec ts;
193
194   DALI_LOG_INFO( gPepperOutputLogging, Debug::Verbose, "Output::OnStartRepaintLoop\n" );
195
196   pepper_compositor_get_time( static_cast< pepper_compositor_t* >( Pepper::GetImplementation( output->mCompositor ).GetCompositorHandle() ), &ts );
197   pepper_output_finish_frame( output->mOutput, &ts );
198 }
199
200 void Output::OnRepaint( void* data, const pepper_list_t* planeList )
201 {
202   Output* output = static_cast< Output* >( data );
203
204   DALI_LOG_INFO( gPepperOutputLogging, Debug::Verbose, "Output::OnRepaint\n" );
205
206   output->mRepaintRequest = true;
207
208   // TODO: temp
209   if( !output->mRenderFinishTimer )
210   {
211     output->mRenderFinishTimer= Timer::New(1);
212     output->mRenderFinishTimer.TickSignal().Connect( output, &Output::OnRenderFinishTimerTick );
213   }
214
215   output->mRenderFinishTimer.Start();
216 }
217
218 void Output::OnAttachSurface( void* data, pepper_surface_t* surface, int* width, int* height )
219 {
220   Output* output = static_cast< Output* >( data );
221   Pepper::Object object;
222
223   DALI_LOG_INFO( gPepperOutputLogging, Debug::Verbose, "Output::OnAttachSurface: surface = %p\n", surface );
224
225   long index = reinterpret_cast< long >( pepper_object_get_user_data( (pepper_object_t*)surface, output ) );
226   if( index == 0 )
227   {
228     object = Pepper::Object::New( surface, output->mInput );
229
230     object.ObjectViewAddedSignal().Connect( output, &Output::OnObjectViewAdded );
231     object.ObjectViewDeletedSignal().Connect( output, &Output::OnObjectViewDeleted );
232
233     index = output->mObjectList.size() + 1;
234     output->mObjectList.push_back( object );
235
236     pepper_object_set_user_data( (pepper_object_t*)surface, output, reinterpret_cast< void* >( index ), NULL );
237
238     DALI_LOG_INFO( gPepperOutputLogging, Debug::Verbose, "Output::OnAttachSurface: object index = %d\n", index );
239   }
240   else
241   {
242     object = output->mObjectList[index - 1];
243   }
244
245   if( !object.AttchBuffer( width, height ) )
246   {
247     *width = 0;
248     *height = 0;
249   }
250
251   // TODO: temp
252   struct timespec ts;
253
254   pepper_compositor_get_time( static_cast< pepper_compositor_t* >( Pepper::GetImplementation( output->mCompositor ).GetCompositorHandle() ), &ts );
255   pepper_output_finish_frame( output->mOutput, &ts );
256 }
257
258 void Output::OnFlushSurface( void* data, pepper_surface_t* surface, pepper_bool_t* keepBuffer )
259 {
260 }
261
262 Pepper::Output::OutputSignalType& Output::ObjectViewAddedSignal()
263 {
264   return mObjectViewAddedSignal;
265 }
266
267 Pepper::Output::OutputSignalType& Output::ObjectViewDeletedSignal()
268 {
269   return mObjectViewDeletedSignal;
270 }
271
272 void Output::OnResize( Application& application )
273 {
274   RenderSurface& surface = Adaptor::Get().GetSurface();
275   PositionSize positionSize = surface.GetPositionSize();
276
277   mSize.width = positionSize.width;
278   mSize.height = positionSize.height;
279
280   pepper_output_update_mode( mOutput );
281 }
282
283 void Output::OnObjectViewAdded( Pepper::Object object, Pepper::ObjectView objectView )
284 {
285   Pepper::Output handle( this );
286   mObjectViewAddedSignal.Emit( handle, objectView );
287 }
288
289 void Output::OnObjectViewDeleted( Pepper::Object object, Pepper::ObjectView objectView )
290 {
291   Pepper::Output handle( this );
292   mObjectViewDeletedSignal.Emit( handle, objectView );
293
294   for ( std::vector< Pepper::Object >::iterator iter = mObjectList.begin(); mObjectList.end() != iter; ++iter )
295   {
296     if( *iter == object )
297     {
298       mObjectList.erase( iter );
299       break;
300     }
301   }
302 }
303
304 void Output::PostRenderComplete()
305 {
306   if( mRepaintRequest )
307   {
308     struct timespec ts;
309
310     DALI_LOG_INFO( gPepperOutputLogging, Debug::Verbose, "Output::PostRenderComplete" );
311
312     pepper_compositor_get_time( static_cast< pepper_compositor_t* >( Pepper::GetImplementation( mCompositor ).GetCompositorHandle() ), &ts );
313     pepper_output_finish_frame( mOutput, &ts );
314
315     mRepaintRequest = false;
316   }
317 }
318
319 void Output::PostRenderStarted()
320 {
321   // Do nothing
322 }
323
324 void Output::PostRenderWaitForCompletion()
325 {
326   // Do nothing
327 }
328
329 // TODO: temp
330 bool Output::OnRenderFinishTimerTick()
331 {
332   struct timespec ts;
333
334   DALI_LOG_INFO( gPepperOutputLogging, Debug::Verbose, "Output::OnRenderFinishTimerTick\n" );
335
336   pepper_compositor_get_time( static_cast< pepper_compositor_t* >( Pepper::GetImplementation( mCompositor ).GetCompositorHandle() ), &ts );
337   pepper_output_finish_frame( mOutput, &ts );
338
339   return false;
340 }
341
342 } // namespace Internal
343
344 } // namespace Pepper
345
346 } // namespace Dali