Merge "Reduce Render::Texture size by 30% and texture upload message size by 50%...
[platform/core/uifw/dali-core.git] / dali / internal / render / common / render-manager.cpp
1 /*
2  * Copyright (c) 2017 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/render/common/render-manager.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/actors/sampling.h>
23 #include <dali/public-api/common/dali-common.h>
24 #include <dali/public-api/common/stage.h>
25 #include <dali/public-api/render-tasks/render-task.h>
26 #include <dali/integration-api/debug.h>
27 #include <dali/integration-api/core.h>
28 #include <dali/internal/common/owner-pointer.h>
29 #include <dali/internal/render/common/render-algorithms.h>
30 #include <dali/internal/render/common/render-debug.h>
31 #include <dali/internal/render/common/render-tracker.h>
32 #include <dali/internal/render/common/render-instruction-container.h>
33 #include <dali/internal/render/common/render-instruction.h>
34 #include <dali/internal/render/gl-resources/context.h>
35 #include <dali/internal/render/queue/render-queue.h>
36 #include <dali/internal/render/renderers/render-frame-buffer.h>
37 #include <dali/internal/render/renderers/render-geometry.h>
38 #include <dali/internal/render/renderers/render-renderer.h>
39 #include <dali/internal/render/renderers/render-sampler.h>
40 #include <dali/internal/render/shaders/program-controller.h>
41
42 namespace Dali
43 {
44
45 namespace Internal
46 {
47
48 namespace SceneGraph
49 {
50
51 /**
52  * Structure to contain internal data
53  */
54 struct RenderManager::Impl
55 {
56   Impl( Integration::GlAbstraction& glAbstraction,
57         Integration::GlSyncAbstraction& glSyncAbstraction )
58   : context( glAbstraction ),
59     glSyncAbstraction( glSyncAbstraction ),
60     renderQueue(),
61     instructions(),
62     backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
63     frameCount( 0 ),
64     renderBufferIndex( SceneGraphBuffers::INITIAL_UPDATE_BUFFER_INDEX ),
65     defaultSurfaceRect(),
66     rendererContainer(),
67     samplerContainer(),
68     textureContainer(),
69     frameBufferContainer(),
70     lastFrameWasRendered( false ),
71     programController( glAbstraction )
72   {
73   }
74
75   ~Impl()
76   {
77   }
78
79   void AddRenderTracker( Render::RenderTracker* renderTracker )
80   {
81     DALI_ASSERT_DEBUG( renderTracker != NULL );
82     mRenderTrackers.PushBack( renderTracker );
83   }
84
85   void RemoveRenderTracker( Render::RenderTracker* renderTracker )
86   {
87     mRenderTrackers.EraseObject( renderTracker );
88   }
89
90   void UpdateTrackers()
91   {
92     for( auto&& iter : mRenderTrackers )
93     {
94       iter->PollSyncObject();
95     }
96   }
97
98   // the order is important for destruction,
99   // programs are owned by context at the moment.
100   Context                                   context;                 ///< holds the GL state
101   Integration::GlSyncAbstraction&           glSyncAbstraction;       ///< GL sync abstraction
102   RenderQueue                               renderQueue;             ///< A message queue for receiving messages from the update-thread.
103
104   // Render instructions describe what should be rendered during RenderManager::Render()
105   // Owned by RenderManager. Update manager updates instructions for the next frame while we render the current one
106   RenderInstructionContainer                instructions;
107
108   Vector4                                   backgroundColor;         ///< The glClear color used at the beginning of each frame.
109
110   unsigned int                              frameCount;              ///< The current frame count
111   BufferIndex                               renderBufferIndex;       ///< The index of the buffer to read from; this is opposite of the "update" buffer
112
113   Rect<int>                                 defaultSurfaceRect;      ///< Rectangle for the default surface we are rendering to
114
115   OwnerContainer< Render::Renderer* >       rendererContainer;       ///< List of owned renderers
116   OwnerContainer< Render::Sampler* >        samplerContainer;        ///< List of owned samplers
117   OwnerContainer< Render::Texture* >        textureContainer;        ///< List of owned textures
118   OwnerContainer< Render::FrameBuffer* >    frameBufferContainer;    ///< List of owned framebuffers
119   OwnerContainer< Render::PropertyBuffer* > propertyBufferContainer; ///< List of owned property buffers
120   OwnerContainer< Render::Geometry* >       geometryContainer;       ///< List of owned Geometries
121
122   bool                                      lastFrameWasRendered;    ///< Keeps track of the last frame being rendered due to having render instructions
123
124   OwnerContainer< Render::RenderTracker* >  mRenderTrackers;         ///< List of render trackers
125
126   ProgramController                         programController;        ///< Owner of the GL programs
127
128 };
129
130 RenderManager* RenderManager::New( Integration::GlAbstraction& glAbstraction,
131                                    Integration::GlSyncAbstraction& glSyncAbstraction )
132 {
133   RenderManager* manager = new RenderManager;
134   manager->mImpl = new Impl( glAbstraction,
135                              glSyncAbstraction );
136   return manager;
137 }
138
139 RenderManager::RenderManager()
140 : mImpl(NULL)
141 {
142 }
143
144 RenderManager::~RenderManager()
145 {
146   delete mImpl;
147 }
148
149 RenderQueue& RenderManager::GetRenderQueue()
150 {
151   return mImpl->renderQueue;
152 }
153
154 void RenderManager::ContextCreated()
155 {
156   mImpl->context.GlContextCreated();
157   mImpl->programController.GlContextCreated();
158
159   // renderers, textures and gpu buffers cannot reinitialize themselves
160   // so they rely on someone reloading the data for them
161 }
162
163 void RenderManager::ContextDestroyed()
164 {
165   mImpl->context.GlContextDestroyed();
166   mImpl->programController.GlContextDestroyed();
167
168   //Inform textures
169   for( auto&& texture : mImpl->textureContainer )
170   {
171     texture->GlContextDestroyed();
172   }
173
174   //Inform framebuffers
175   for( auto&& framebuffer : mImpl->frameBufferContainer )
176   {
177     framebuffer->GlContextDestroyed();
178   }
179
180   // inform renderers
181   for( auto&& renderer : mImpl->rendererContainer )
182   {
183     renderer->GlContextDestroyed();
184   }
185 }
186
187 void RenderManager::SetShaderSaver( ShaderSaver& upstream )
188 {
189   mImpl->programController.SetShaderSaver( upstream );
190 }
191
192 RenderInstructionContainer& RenderManager::GetRenderInstructionContainer()
193 {
194   return mImpl->instructions;
195 }
196
197 void RenderManager::SetBackgroundColor( const Vector4& color )
198 {
199   mImpl->backgroundColor = color;
200 }
201
202 void RenderManager::SetDefaultSurfaceRect(const Rect<int>& rect)
203 {
204   mImpl->defaultSurfaceRect = rect;
205 }
206
207 void RenderManager::AddRenderer( OwnerPointer< Render::Renderer >& renderer )
208 {
209   // Initialize the renderer as we are now in render thread
210   renderer->Initialize( mImpl->context );
211
212   mImpl->rendererContainer.PushBack( renderer.Release() );
213 }
214
215 void RenderManager::RemoveRenderer( Render::Renderer* renderer )
216 {
217   mImpl->rendererContainer.EraseObject( renderer );
218 }
219
220 void RenderManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
221 {
222   mImpl->samplerContainer.PushBack( sampler.Release() );
223 }
224
225 void RenderManager::RemoveSampler( Render::Sampler* sampler )
226 {
227   mImpl->samplerContainer.EraseObject( sampler );
228 }
229
230 void RenderManager::AddTexture( OwnerPointer< Render::Texture >& texture )
231 {
232   texture->Initialize( mImpl->context );
233   mImpl->textureContainer.PushBack( texture.Release() );
234 }
235
236 void RenderManager::RemoveTexture( Render::Texture* texture )
237 {
238   DALI_ASSERT_DEBUG( NULL != texture );
239
240   // Find the texture, use reference to pointer so we can do the erase safely
241   for ( auto&& iter : mImpl->textureContainer )
242   {
243     if ( iter == texture )
244     {
245       texture->Destroy( mImpl->context );
246       mImpl->textureContainer.Erase( &iter ); // Texture found; now destroy it
247       return;
248     }
249   }
250 }
251
252 void RenderManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
253 {
254   texture->Upload( mImpl->context, pixelData, params );
255 }
256
257 void RenderManager::GenerateMipmaps( Render::Texture* texture )
258 {
259   texture->GenerateMipmaps( mImpl->context );
260 }
261
262 void RenderManager::SetFilterMode( Render::Sampler* sampler, unsigned int minFilterMode, unsigned int magFilterMode )
263 {
264   sampler->mMinificationFilter = static_cast<Dali::FilterMode::Type>(minFilterMode);
265   sampler->mMagnificationFilter = static_cast<Dali::FilterMode::Type>(magFilterMode );
266 }
267
268 void RenderManager::SetWrapMode( Render::Sampler* sampler, unsigned int rWrapMode, unsigned int sWrapMode, unsigned int tWrapMode )
269 {
270   sampler->mRWrapMode = static_cast<Dali::WrapMode::Type>(rWrapMode);
271   sampler->mSWrapMode = static_cast<Dali::WrapMode::Type>(sWrapMode);
272   sampler->mTWrapMode = static_cast<Dali::WrapMode::Type>(tWrapMode);
273 }
274
275 void RenderManager::AddFrameBuffer( Render::FrameBuffer* frameBuffer )
276 {
277   mImpl->frameBufferContainer.PushBack( frameBuffer );
278   frameBuffer->Initialize(mImpl->context);
279 }
280
281 void RenderManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer )
282 {
283   DALI_ASSERT_DEBUG( NULL != frameBuffer );
284
285   // Find the sampler, use reference so we can safely do the erase
286   for ( auto&& iter : mImpl->frameBufferContainer )
287   {
288     if ( iter == frameBuffer )
289     {
290       frameBuffer->Destroy( mImpl->context );
291       mImpl->frameBufferContainer.Erase( &iter ); // frameBuffer found; now destroy it
292       break;
293     }
294   }
295 }
296
297 void RenderManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, unsigned int mipmapLevel, unsigned int layer )
298 {
299   frameBuffer->AttachColorTexture( mImpl->context, texture, mipmapLevel, layer );
300 }
301
302 void RenderManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
303 {
304   mImpl->propertyBufferContainer.PushBack( propertyBuffer.Release() );
305 }
306
307 void RenderManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
308 {
309   mImpl->propertyBufferContainer.EraseObject( propertyBuffer );
310 }
311
312 void RenderManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
313 {
314   propertyBuffer->SetFormat( format.Release() );
315 }
316
317 void RenderManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<char> >& data, size_t size )
318 {
319   propertyBuffer->SetData( data.Release(), size );
320 }
321
322 void RenderManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<unsigned short>& indices )
323 {
324   geometry->SetIndexBuffer( indices );
325 }
326
327 void RenderManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
328 {
329   mImpl->geometryContainer.PushBack( geometry.Release() );
330 }
331
332 void RenderManager::RemoveGeometry( Render::Geometry* geometry )
333 {
334   mImpl->geometryContainer.EraseObject( geometry );
335 }
336
337 void RenderManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
338 {
339   DALI_ASSERT_DEBUG( NULL != geometry );
340
341   // Find the geometry
342   for ( auto&& iter : mImpl->geometryContainer )
343   {
344     if ( iter == geometry )
345     {
346       iter->AddPropertyBuffer( propertyBuffer );
347       break;
348     }
349   }
350 }
351
352 void RenderManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
353 {
354   DALI_ASSERT_DEBUG( NULL != geometry );
355
356   // Find the geometry
357   for ( auto&& iter : mImpl->geometryContainer )
358   {
359     if ( iter == geometry )
360     {
361       iter->RemovePropertyBuffer( propertyBuffer );
362       break;
363     }
364   }
365 }
366
367 void RenderManager::SetGeometryType( Render::Geometry* geometry, unsigned int geometryType )
368 {
369   geometry->SetType( Render::Geometry::Type(geometryType) );
370 }
371
372 void RenderManager::AddRenderTracker( Render::RenderTracker* renderTracker )
373 {
374   mImpl->AddRenderTracker(renderTracker);
375 }
376
377 void RenderManager::RemoveRenderTracker( Render::RenderTracker* renderTracker )
378 {
379   mImpl->RemoveRenderTracker(renderTracker);
380 }
381
382 ProgramCache* RenderManager::GetProgramCache()
383 {
384   return &(mImpl->programController);
385 }
386
387 void RenderManager::Render( Integration::RenderStatus& status )
388 {
389   DALI_PRINT_RENDER_START( mImpl->renderBufferIndex );
390
391   // Core::Render documents that GL context must be current before calling Render
392   DALI_ASSERT_DEBUG( mImpl->context.IsGlContextCreated() );
393
394   // Increment the frame count at the beginning of each frame
395   ++(mImpl->frameCount);
396
397   // Process messages queued during previous update
398   mImpl->renderQueue.ProcessMessages( mImpl->renderBufferIndex );
399
400   const size_t count = mImpl->instructions.Count( mImpl->renderBufferIndex );
401   const bool haveInstructions = count > 0u;
402
403   // Only render if we have instructions to render, or the last frame was rendered (and therefore a clear is required).
404   if( haveInstructions || mImpl->lastFrameWasRendered )
405   {
406     // Mark that we will require a post-render step to be performed (includes swap-buffers).
407     status.SetNeedsPostRender( true );
408
409     // switch rendering to adaptor provided (default) buffer
410     mImpl->context.BindFramebuffer( GL_FRAMEBUFFER, 0 );
411
412     mImpl->context.Viewport( mImpl->defaultSurfaceRect.x,
413                              mImpl->defaultSurfaceRect.y,
414                              mImpl->defaultSurfaceRect.width,
415                              mImpl->defaultSurfaceRect.height );
416
417     mImpl->context.ClearColor( mImpl->backgroundColor.r,
418                                mImpl->backgroundColor.g,
419                                mImpl->backgroundColor.b,
420                                mImpl->backgroundColor.a );
421
422     mImpl->context.ClearStencil( 0 );
423
424     // Clear the entire color, depth and stencil buffers for the default framebuffer.
425     // It is important to clear all 3 buffers, for performance on deferred renderers like Mali
426     // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit",
427     // and then stall. That problem is only noticeable when rendering a large number of vertices per frame.
428     mImpl->context.SetScissorTest( false );
429     mImpl->context.ColorMask( true );
430     mImpl->context.DepthMask( true );
431     mImpl->context.StencilMask( 0xFF ); // 8 bit stencil mask, all 1's
432     mImpl->context.Clear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, Context::FORCE_CLEAR );
433
434     // reset the program matrices for all programs once per frame
435     // this ensures we will set view and projection matrix once per program per camera
436     mImpl->programController.ResetProgramMatrices();
437
438     for( size_t i = 0; i < count; ++i )
439     {
440       RenderInstruction& instruction = mImpl->instructions.At( mImpl->renderBufferIndex, i );
441
442       DoRender( instruction );
443     }
444
445     GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
446     mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
447
448     mImpl->UpdateTrackers();
449
450     //Notify RenderGeometries that rendering has finished
451     for ( auto&& iter : mImpl->geometryContainer )
452     {
453       iter->OnRenderFinished();
454     }
455   }
456
457   // If this frame was rendered due to instructions existing, we mark this so we know to clear the next frame.
458   mImpl->lastFrameWasRendered = haveInstructions;
459
460   /**
461    * The rendering has finished; swap to the next buffer.
462    * Ideally the update has just finished using this buffer; otherwise the render thread
463    * should block until the update has finished.
464    */
465   mImpl->renderBufferIndex = (0 != mImpl->renderBufferIndex) ? 0 : 1;
466
467   DALI_PRINT_RENDER_END();
468 }
469
470 void RenderManager::DoRender( RenderInstruction& instruction )
471 {
472   Rect<int> viewportRect;
473   Vector4   clearColor;
474
475   if ( instruction.mIsClearColorSet )
476   {
477     clearColor = instruction.mClearColor;
478   }
479   else
480   {
481     clearColor = Dali::RenderTask::DEFAULT_CLEAR_COLOR;
482   }
483
484   if( instruction.mFrameBuffer != 0 )
485   {
486     instruction.mFrameBuffer->Bind( mImpl->context );
487     if ( instruction.mIsViewportSet )
488     {
489       // For glViewport the lower-left corner is (0,0)
490       const int y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
491       viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
492     }
493     else
494     {
495       viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
496     }
497   }
498   else // !(instruction.mOffscreenTexture)
499   {
500     // switch rendering to adaptor provided (default) buffer
501     mImpl->context.BindFramebuffer( GL_FRAMEBUFFER, 0 );
502
503     // Check whether a viewport is specified, otherwise the full surface size is used
504     if ( instruction.mIsViewportSet )
505     {
506       // For glViewport the lower-left corner is (0,0)
507       const int y = ( mImpl->defaultSurfaceRect.height - instruction.mViewport.height ) - instruction.mViewport.y;
508       viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
509     }
510     else
511     {
512       viewportRect = mImpl->defaultSurfaceRect;
513     }
514   }
515
516   mImpl->context.Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
517
518   if ( instruction.mIsClearColorSet )
519   {
520     mImpl->context.ClearColor( clearColor.r,
521                                clearColor.g,
522                                clearColor.b,
523                                clearColor.a );
524
525     // Clear the viewport area only
526     mImpl->context.SetScissorTest( true );
527     mImpl->context.Scissor( viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height );
528     mImpl->context.ColorMask( true );
529     mImpl->context.Clear( GL_COLOR_BUFFER_BIT , Context::CHECK_CACHED_VALUES );
530     mImpl->context.SetScissorTest( false );
531   }
532
533   Render::ProcessRenderInstruction( instruction,
534                                     mImpl->context,
535                                     mImpl->renderBufferIndex );
536
537   if( instruction.mRenderTracker && ( instruction.mFrameBuffer != NULL ) )
538   {
539     // This will create a sync object every frame this render tracker
540     // is alive (though it should be now be created only for
541     // render-once render tasks)
542     instruction.mRenderTracker->CreateSyncObject( mImpl->glSyncAbstraction );
543     instruction.mRenderTracker = NULL; // Only create once.
544   }
545 }
546
547 } // namespace SceneGraph
548
549 } // namespace Internal
550
551 } // namespace Dali