b2cc5a7f850cec61af0daef7b85af41d8be058dd
[platform/core/uifw/dali-adaptor.git] / adaptors / mobile / mobile-native-buffer-render-surface.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 "mobile-native-buffer-render-surface.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <dali/integration-api/gl-abstraction.h>
24 #include <native-buffer-pool.h>
25
26 // INTERANL INCLUDES
27 #include <gl/egl-implementation.h>
28 #include <trigger-event.h>
29
30 namespace Dali
31 {
32
33 namespace Internal
34 {
35
36 namespace Adaptor
37 {
38
39 #if defined(DEBUG_ENABLED)
40 extern Debug::Filter* gRenderSurfaceLogFilter;
41 #endif
42
43 namespace ECore
44 {
45
46 NativeBufferRenderSurface::NativeBufferRenderSurface( native_buffer_provider* provider,
47                                                       native_buffer_pool* pool,
48                                                       unsigned int maxBufferCount,
49                                                       Dali::PositionSize positionSize,
50                                                       Any surface,
51                                                       Any display,
52                                                       const std::string& name,
53                                                       bool isTransparent )
54 : RenderSurface( Dali::RenderSurface::NATIVE_BUFFER, positionSize, surface, display, "native_buffer", isTransparent ),
55   mProvider( provider ),
56   mPool( pool ),
57   mMaxBufferCount( maxBufferCount ),
58   mIsAcquired( false )
59 {
60   DALI_ASSERT_ALWAYS(maxBufferCount > 0);
61   Init( surface );
62 }
63
64 NativeBufferRenderSurface::~NativeBufferRenderSurface()
65 {
66   DALI_LOG_WARNING("%d native buffer will be destroyed\n", mBuffers.size());
67
68   // destroy buffers
69   NativeBufferContainer::iterator bufferIter;
70   for (bufferIter = mBuffers.begin(); bufferIter != mBuffers.end(); ++bufferIter)
71   {
72     native_buffer_destroy((*bufferIter));
73   }
74   mBuffers.clear();
75 }
76
77 Ecore_X_Drawable NativeBufferRenderSurface::GetDrawable()
78 {
79   return (Ecore_X_Drawable)0;
80 }
81
82 Dali::RenderSurface::SurfaceType NativeBufferRenderSurface::GetType()
83 {
84   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
85   return Dali::RenderSurface::NATIVE_BUFFER;
86 }
87
88 Any NativeBufferRenderSurface::GetSurface()
89 {
90   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
91   return Any();
92 }
93
94 void NativeBufferRenderSurface::InitializeEgl( EglInterface& egl )
95 {
96   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
97
98   EglImplementation& eglImpl = static_cast<EglImplementation&>( egl );
99   eglImpl.InitializeGles( reinterpret_cast< EGLNativeDisplayType >( mMainDisplay ), false /* external surface */);
100
101   eglImpl.ChooseConfig(false, mColorDepth);
102 }
103
104 native_buffer* NativeBufferRenderSurface::CreateNativeBuffer()
105 {
106   native_buffer* buffer;
107
108   buffer = native_buffer_create(mProvider, mPosition.width, mPosition.height,
109     mColorDepth == COLOR_DEPTH_32? mPosition.width * 4 : mPosition.width * 3, /* stride will be deprecated */
110     mColorDepth == COLOR_DEPTH_32? NATIVE_BUFFER_FORMAT_BGRA_8888 : NATIVE_BUFFER_FORMAT_RGB_888,
111     NATIVE_BUFFER_USAGE_3D_RENDER);
112
113   if(buffer)
114   {
115     // insert buffer to list
116     mBuffers.push_back(buffer);
117   }
118
119   return buffer;
120 }
121
122 void NativeBufferRenderSurface::CreateEglSurface( EglInterface& egl )
123 {
124   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
125
126   EglImplementation& eglImpl = static_cast<EglImplementation&>( egl );
127
128   // create one buffer
129   native_buffer_pool_add_buffer(mPool, CreateNativeBuffer());
130
131   DALI_ASSERT_ALWAYS( native_buffer_pool_acquire_surface( mPool, eglImpl.GetDisplay(), eglImpl.GetContext() ) == STATUS_SUCCESS );
132   mIsAcquired = true;
133 }
134
135 void NativeBufferRenderSurface::DestroyEglSurface( EglInterface& egl )
136 {
137   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
138
139   // Remove buffers from pool
140   native_buffer_pool_reset(mPool);
141 }
142
143 bool NativeBufferRenderSurface::ReplaceEGLSurface( EglInterface& egl )
144 {
145   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
146
147   return false;
148 }
149
150 bool NativeBufferRenderSurface::PreRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction )
151 {
152   EglImplementation& eglImpl = static_cast<EglImplementation&>( egl );
153
154   if(mIsAcquired)
155   {
156     mIsAcquired = false;
157     return true;
158   }
159
160   // Attempt to acquire a surface for rendering
161   while( !mIsStopped && native_buffer_pool_get_input_buffer_count(mPool) < 1 )
162   {
163     if(mBuffers.size() <= mMaxBufferCount)
164     {
165       // create one buffer
166       native_buffer_pool_add_buffer(mPool, CreateNativeBuffer());
167     }
168     else
169     {
170       usleep( 5 * 1000 );  // polling per 5 msec
171     }
172   }
173
174   if( !mIsStopped && native_buffer_pool_acquire_surface( mPool, eglImpl.GetDisplay(), eglImpl.GetContext() ) != STATUS_SUCCESS )
175   {
176     DALI_LOG_ERROR("Failed to acquire native buffer surface (# queue : %d)\n", native_buffer_pool_get_input_buffer_count(mPool));
177   }
178
179   return !mIsStopped; // fail if it is stopped
180 }
181
182 void NativeBufferRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, unsigned int timeDelta, SyncMode syncMode )
183 {
184   glAbstraction.Flush();
185
186   // release the surface to allow consumer usage
187   if(native_buffer_pool_release_surface( mPool ) != STATUS_SUCCESS)
188   {
189     DALI_LOG_ERROR("Failed to release native buffer surface (# queue : %d)\n", native_buffer_pool_get_input_buffer_count(mPool));
190   }
191
192   // create damage for client applications which wish to know the update timing
193   if( mRenderNotification )
194   {
195     // use notification trigger
196     // Tell the event-thread to render the pixmap
197     mRenderNotification->Trigger();
198   }
199
200   // Do render synchronisation
201   DoRenderSync( timeDelta, syncMode );
202 }
203
204 void NativeBufferRenderSurface::CreateXRenderable()
205 {
206   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
207
208   // nothing to do
209 }
210
211 void NativeBufferRenderSurface::UseExistingRenderable( unsigned int surfaceId )
212 {
213   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
214
215   // nothing to do
216 }
217
218 } // namespace ECore
219
220 } // namespace Adaptor
221
222 } // namespace Internal
223
224 } // namespace Dali