Revert "[Tizen] Add screen and client rotation itself function"
[platform/core/uifw/dali-adaptor.git] / dali / internal / window-system / tizen-wayland / native-render-surface-ecore-wl.cpp
1 /*
2  * Copyright (c) 2020 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 <dali/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/gl-abstraction.h>
23 #include <dali/integration-api/debug.h>
24
25 #ifdef ECORE_WAYLAND2
26 #include <Ecore_Wl2.h>
27 #else
28 #include <Ecore_Wayland.h>
29 #endif
30
31 #include <tbm_bufmgr.h>
32 #include <tbm_surface_internal.h>
33
34 // INTERNAL INCLUDES
35 #include <dali/integration-api/adaptor-framework/thread-synchronization-interface.h>
36 #include <dali/internal/adaptor/common/adaptor-impl.h>
37 #include <dali/internal/adaptor/common/adaptor-internal-services.h>
38 #include <dali/internal/graphics/gles/egl-graphics.h>
39 #include <dali/internal/graphics/gles/egl-implementation.h>
40 #include <dali/internal/system/common/trigger-event.h>
41 #include <dali/internal/window-system/common/display-connection.h>
42 #include <dali/internal/window-system/common/window-system.h>
43
44 namespace Dali
45 {
46
47 namespace
48 {
49
50 #if defined(DEBUG_ENABLED)
51 Debug::Filter* gNativeSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_NATIVE_RENDER_SURFACE");
52 #endif
53
54 } // unnamed namespace
55
56 NativeRenderSurfaceEcoreWl::NativeRenderSurfaceEcoreWl( SurfaceSize surfaceSize, Any surface, bool isTransparent )
57 : mSurfaceSize( surfaceSize ),
58   mRenderNotification( NULL ),
59   mGraphics( NULL ),
60   mEGL( nullptr ),
61   mEGLSurface( nullptr ),
62   mEGLContext( nullptr ),
63   mColorDepth( isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24 ),
64   mTbmFormat( isTransparent ? TBM_FORMAT_ARGB8888 : TBM_FORMAT_RGB888 ),
65   mOwnSurface( false ),
66   mDrawableCompleted( false ),
67   mTbmQueue( NULL ),
68   mConsumeSurface( NULL ),
69   mThreadSynchronization( NULL )
70 {
71   Dali::Internal::Adaptor::WindowSystem::Initialize();
72
73   if( surface.Empty() )
74   {
75     CreateNativeRenderable();
76   }
77   else
78   {
79     // check we have a valid type
80     DALI_ASSERT_ALWAYS( ( surface.GetType() == typeid (tbm_surface_queue_h) ) && "Surface type is invalid" );
81     mTbmQueue = AnyCast< tbm_surface_queue_h >( surface );
82   }
83 }
84
85 NativeRenderSurfaceEcoreWl::~NativeRenderSurfaceEcoreWl()
86 {
87   if ( mEGLSurface )
88   {
89     DestroySurface();
90   }
91
92   // release the surface if we own one
93   if( mOwnSurface )
94   {
95     ReleaseDrawable();
96
97     if( mTbmQueue )
98     {
99       tbm_surface_queue_destroy( mTbmQueue );
100     }
101
102     DALI_LOG_INFO( gNativeSurfaceLogFilter, Debug::General, "Own tbm surface queue destroy\n" );
103   }
104
105   Dali::Internal::Adaptor::WindowSystem::Shutdown();
106 }
107
108 Any NativeRenderSurfaceEcoreWl::GetDrawable()
109 {
110   return mConsumeSurface;
111 }
112
113 void NativeRenderSurfaceEcoreWl::SetRenderNotification( TriggerEventInterface* renderNotification )
114 {
115   mRenderNotification = renderNotification;
116 }
117
118 void NativeRenderSurfaceEcoreWl::WaitUntilSurfaceReplaced()
119 {
120   ConditionalWait::ScopedLock lock( mTbmSurfaceCondition );
121   while( !mDrawableCompleted )
122   {
123     mTbmSurfaceCondition.Wait( lock );
124   }
125
126   mDrawableCompleted = false;
127 }
128
129 PositionSize NativeRenderSurfaceEcoreWl::GetPositionSize() const
130 {
131   return PositionSize( 0, 0, static_cast<int>( mSurfaceSize.GetWidth() ), static_cast<int>( mSurfaceSize.GetHeight() ) );
132 }
133
134 void NativeRenderSurfaceEcoreWl::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical )
135 {
136   // calculate DPI
137   float xres, yres;
138
139   // 1 inch = 25.4 millimeters
140 #ifdef ECORE_WAYLAND2
141   // TODO: Application should set dpi value in wayland2
142   xres = 96;
143   yres = 96;
144 #else
145   xres = ecore_wl_dpi_get();
146   yres = ecore_wl_dpi_get();
147 #endif
148
149   dpiHorizontal = int( xres + 0.5f );  // rounding
150   dpiVertical   = int( yres + 0.5f );
151 }
152
153 void NativeRenderSurfaceEcoreWl::InitializeGraphics()
154 {
155   DALI_LOG_TRACE_METHOD( gNativeSurfaceLogFilter );
156
157   mGraphics = &mAdaptor->GetGraphicsInterface();
158   auto eglGraphics = static_cast<Internal::Adaptor::EglGraphics *>(mGraphics);
159
160   mEGL = &eglGraphics->GetEglInterface();
161
162   if ( mEGLContext == NULL )
163   {
164     // Create the OpenGL context for this window
165     Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>(*mEGL);
166     eglImpl.CreateWindowContext( mEGLContext );
167
168     // Create the OpenGL surface
169     CreateSurface();
170   }
171 }
172
173 void NativeRenderSurfaceEcoreWl::CreateSurface()
174 {
175   DALI_LOG_TRACE_METHOD( gNativeSurfaceLogFilter );
176
177   auto eglGraphics = static_cast<Internal::Adaptor::EglGraphics *>(mGraphics);
178   Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
179
180   mEGLSurface = eglImpl.CreateSurfaceWindow( reinterpret_cast< EGLNativeWindowType >( mTbmQueue ), mColorDepth );
181 }
182
183 void NativeRenderSurfaceEcoreWl::DestroySurface()
184 {
185   DALI_LOG_TRACE_METHOD( gNativeSurfaceLogFilter );
186
187   auto eglGraphics = static_cast<Internal::Adaptor::EglGraphics *>(mGraphics);
188   Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
189
190   eglImpl.DestroySurface( mEGLSurface );
191 }
192
193 bool NativeRenderSurfaceEcoreWl::ReplaceGraphicsSurface()
194 {
195   DALI_LOG_TRACE_METHOD( gNativeSurfaceLogFilter );
196
197   if( !mTbmQueue )
198   {
199     return false;
200   }
201
202   auto eglGraphics = static_cast<Internal::Adaptor::EglGraphics *>(mGraphics);
203   Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
204
205   return eglImpl.ReplaceSurfaceWindow( reinterpret_cast< EGLNativeWindowType >( mTbmQueue ), mEGLSurface, mEGLContext );
206 }
207
208 void NativeRenderSurfaceEcoreWl::MoveResize( Dali::PositionSize positionSize )
209 {
210   tbm_surface_queue_error_e error = TBM_SURFACE_QUEUE_ERROR_NONE;
211
212   error = tbm_surface_queue_reset( mTbmQueue, positionSize.width, positionSize.height, mTbmFormat );
213
214   if( error != TBM_SURFACE_QUEUE_ERROR_NONE )
215   {
216     DALI_LOG_ERROR( "Failed to resize tbm_surface_queue" );
217   }
218
219   mSurfaceSize.SetWidth( static_cast<uint16_t>( positionSize.width ) );
220   mSurfaceSize.SetHeight( static_cast<uint16_t>( positionSize.height ) );
221 }
222
223 void NativeRenderSurfaceEcoreWl::StartRender()
224 {
225 }
226
227 bool NativeRenderSurfaceEcoreWl::PreRender( bool resizingSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect )
228 {
229   auto eglGraphics = static_cast<Internal::Adaptor::EglGraphics*>(mGraphics);
230   if (eglGraphics)
231   {
232     Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
233     if (resizingSurface)
234     {
235       eglImpl.SetFullSwapNextFrame();
236     }
237
238     eglImpl.SetDamage(mEGLSurface, damagedRects, clippingRect);
239   }
240
241   return true;
242 }
243
244 void NativeRenderSurfaceEcoreWl::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects )
245 {
246   auto eglGraphics = static_cast<Internal::Adaptor::EglGraphics *>(mGraphics);
247   if (eglGraphics)
248   {
249     Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
250     eglImpl.SwapBuffers( mEGLSurface, damagedRects );
251   }
252
253   if( mThreadSynchronization )
254   {
255     mThreadSynchronization->PostRenderStarted();
256   }
257
258   if( tbm_surface_queue_can_acquire( mTbmQueue, 1 ) )
259   {
260     if( tbm_surface_queue_acquire( mTbmQueue, &mConsumeSurface ) != TBM_SURFACE_QUEUE_ERROR_NONE )
261     {
262       DALI_LOG_ERROR( "Failed to acquire a tbm_surface\n" );
263       return;
264     }
265   }
266
267   tbm_surface_internal_ref( mConsumeSurface );
268
269   if( replacingSurface )
270   {
271     ConditionalWait::ScopedLock lock( mTbmSurfaceCondition );
272     mDrawableCompleted = true;
273     mTbmSurfaceCondition.Notify( lock );
274   }
275
276  // create damage for client applications which wish to know the update timing
277   if( !replacingSurface && mRenderNotification )
278   {
279     // use notification trigger
280     // Tell the event-thread to render the tbm_surface
281     mRenderNotification->Trigger();
282   }
283
284   if( mThreadSynchronization )
285   {
286     // wait until the event-thread completed to use the tbm_surface
287     mThreadSynchronization->PostRenderWaitForCompletion();
288   }
289
290   // release the consumed surface after post render was completed
291   ReleaseDrawable();
292 }
293
294 void NativeRenderSurfaceEcoreWl::StopRender()
295 {
296   ReleaseLock();
297 }
298
299 void NativeRenderSurfaceEcoreWl::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
300 {
301   mThreadSynchronization = &threadSynchronization;
302 }
303
304 Dali::RenderSurfaceInterface::Type NativeRenderSurfaceEcoreWl::GetSurfaceType()
305 {
306   return Dali::RenderSurfaceInterface::NATIVE_RENDER_SURFACE;
307 }
308
309 void NativeRenderSurfaceEcoreWl::MakeContextCurrent()
310 {
311   if ( mEGL != nullptr )
312   {
313     mEGL->MakeContextCurrent( mEGLSurface, mEGLContext );
314   }
315 }
316
317 Integration::DepthBufferAvailable NativeRenderSurfaceEcoreWl::GetDepthBufferRequired()
318 {
319   return mGraphics ? mGraphics->GetDepthBufferRequired() : Integration::DepthBufferAvailable::FALSE;
320 }
321
322 Integration::StencilBufferAvailable NativeRenderSurfaceEcoreWl::GetStencilBufferRequired()
323 {
324   return mGraphics ? mGraphics->GetStencilBufferRequired() : Integration::StencilBufferAvailable::FALSE;
325 }
326
327 void NativeRenderSurfaceEcoreWl::ReleaseLock()
328 {
329   if( mThreadSynchronization )
330   {
331     mThreadSynchronization->PostRenderComplete();
332   }
333 }
334
335 void NativeRenderSurfaceEcoreWl::CreateNativeRenderable()
336 {
337   int width = static_cast<int>( mSurfaceSize.GetWidth() );
338   int height = static_cast<int>( mSurfaceSize.GetHeight() );
339
340   // check we're creating one with a valid size
341   DALI_ASSERT_ALWAYS( width > 0 && height > 0 && "tbm_surface size is invalid" );
342
343   mTbmQueue = tbm_surface_queue_create( 3, width, height, mTbmFormat, TBM_BO_DEFAULT );
344
345   if( mTbmQueue )
346   {
347     mOwnSurface = true;
348   }
349   else
350   {
351     mOwnSurface = false;
352   }
353 }
354
355 void NativeRenderSurfaceEcoreWl::ReleaseDrawable()
356 {
357   if( mConsumeSurface )
358   {
359     tbm_surface_internal_unref( mConsumeSurface );
360
361     if( tbm_surface_internal_is_valid( mConsumeSurface ) )
362     {
363       tbm_surface_queue_release( mTbmQueue, mConsumeSurface );
364     }
365     mConsumeSurface = NULL;
366   }
367 }
368
369 } // namespace Dali