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