2 * Copyright (c) 2019 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/render/common/render-manager.h>
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-texture-frame-buffer.h>
38 #include <dali/internal/render/renderers/render-surface-frame-buffer.h>
39 #include <dali/internal/render/renderers/render-geometry.h>
40 #include <dali/internal/render/renderers/render-renderer.h>
41 #include <dali/internal/render/renderers/render-sampler.h>
42 #include <dali/internal/render/shaders/program-controller.h>
53 #if defined(DEBUG_ENABLED)
56 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RENDER_MANAGER" );
57 } // unnamed namespace
61 * Structure to contain internal data
63 struct RenderManager::Impl
65 Impl( Integration::GlAbstraction& glAbstraction,
66 Integration::GlSyncAbstraction& glSyncAbstraction,
67 Integration::DepthBufferAvailable depthBufferAvailableParam,
68 Integration::StencilBufferAvailable stencilBufferAvailableParam )
69 : context( glAbstraction ),
70 currentContext( &context ),
71 glAbstraction( glAbstraction ),
72 glSyncAbstraction( glSyncAbstraction ),
76 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
78 renderBufferIndex( SceneGraphBuffers::INITIAL_UPDATE_BUFFER_INDEX ),
83 frameBufferContainer(),
84 lastFrameWasRendered( false ),
85 programController( glAbstraction ),
86 depthBufferAvailable( depthBufferAvailableParam ),
87 stencilBufferAvailable( stencilBufferAvailableParam ),
88 defaultSurfaceOrientation( 0 )
96 void AddRenderTracker( Render::RenderTracker* renderTracker )
98 DALI_ASSERT_DEBUG( renderTracker != NULL );
99 mRenderTrackers.PushBack( renderTracker );
102 void RemoveRenderTracker( Render::RenderTracker* renderTracker )
104 mRenderTrackers.EraseObject( renderTracker );
107 Context* CreateSurfaceContext()
109 surfaceContextContainer.PushBack( new Context( glAbstraction ) );
110 return surfaceContextContainer[ surfaceContextContainer.Count() - 1 ];
113 void DestroySurfaceContext( Context* surfaceContext )
115 surfaceContextContainer.EraseObject( surfaceContext );
118 void UpdateTrackers()
120 for( auto&& iter : mRenderTrackers )
122 iter->PollSyncObject();
126 // the order is important for destruction,
127 // programs are owned by context at the moment.
128 Context context; ///< Holds the GL state of the share resource context
129 Context* currentContext; ///< Holds the GL state of the current context for rendering
130 OwnerContainer< Context* > surfaceContextContainer; ///< List of owned contexts holding the GL state per surface
131 Integration::GlAbstraction& glAbstraction; ///< GL abstraction
132 Integration::GlSyncAbstraction& glSyncAbstraction; ///< GL sync abstraction
133 RenderQueue renderQueue; ///< A message queue for receiving messages from the update-thread.
135 // Render instructions describe what should be rendered during RenderManager::Render()
136 // Owned by RenderManager. Update manager updates instructions for the next frame while we render the current one
137 RenderInstructionContainer instructions;
138 Render::RenderAlgorithms renderAlgorithms; ///< The RenderAlgorithms object is used to action the renders required by a RenderInstruction
140 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
142 uint32_t frameCount; ///< The current frame count
143 BufferIndex renderBufferIndex; ///< The index of the buffer to read from; this is opposite of the "update" buffer
145 Rect<int32_t> defaultSurfaceRect; ///< Rectangle for the default surface we are rendering to
147 OwnerContainer< Render::Renderer* > rendererContainer; ///< List of owned renderers
148 OwnerContainer< Render::Sampler* > samplerContainer; ///< List of owned samplers
149 OwnerContainer< Render::Texture* > textureContainer; ///< List of owned textures
150 OwnerContainer< Render::FrameBuffer* > frameBufferContainer; ///< List of owned framebuffers
151 OwnerContainer< Render::PropertyBuffer* > propertyBufferContainer; ///< List of owned property buffers
152 OwnerContainer< Render::Geometry* > geometryContainer; ///< List of owned Geometries
154 bool lastFrameWasRendered; ///< Keeps track of the last frame being rendered due to having render instructions
156 OwnerContainer< Render::RenderTracker* > mRenderTrackers; ///< List of render trackers
158 ProgramController programController; ///< Owner of the GL programs
160 Integration::DepthBufferAvailable depthBufferAvailable; ///< Whether the depth buffer is available
161 Integration::StencilBufferAvailable stencilBufferAvailable; ///< Whether the stencil buffer is available
163 int defaultSurfaceOrientation; ///< defaultSurfaceOrientation for the default surface we are rendering to
167 RenderManager* RenderManager::New( Integration::GlAbstraction& glAbstraction,
168 Integration::GlSyncAbstraction& glSyncAbstraction,
169 Integration::DepthBufferAvailable depthBufferAvailable,
170 Integration::StencilBufferAvailable stencilBufferAvailable )
172 RenderManager* manager = new RenderManager;
173 manager->mImpl = new Impl( glAbstraction,
175 depthBufferAvailable,
176 stencilBufferAvailable );
180 RenderManager::RenderManager()
185 RenderManager::~RenderManager()
190 RenderQueue& RenderManager::GetRenderQueue()
192 return mImpl->renderQueue;
195 void RenderManager::ContextCreated()
197 mImpl->context.GlContextCreated();
198 mImpl->programController.GlContextCreated();
200 // renderers, textures and gpu buffers cannot reinitialize themselves
201 // so they rely on someone reloading the data for them
204 void RenderManager::ContextDestroyed()
206 mImpl->context.GlContextDestroyed();
207 mImpl->programController.GlContextDestroyed();
210 for( auto&& texture : mImpl->textureContainer )
212 texture->GlContextDestroyed();
215 //Inform framebuffers
216 for( auto&& framebuffer : mImpl->frameBufferContainer )
218 framebuffer->GlContextDestroyed();
222 for( auto&& renderer : mImpl->rendererContainer )
224 renderer->GlContextDestroyed();
228 void RenderManager::SetShaderSaver( ShaderSaver& upstream )
230 mImpl->programController.SetShaderSaver( upstream );
233 RenderInstructionContainer& RenderManager::GetRenderInstructionContainer()
235 return mImpl->instructions;
238 void RenderManager::SetBackgroundColor( const Vector4& color )
240 mImpl->backgroundColor = color;
243 void RenderManager::SetDefaultSurfaceRect(const Rect<int32_t>& rect)
245 mImpl->defaultSurfaceRect = rect;
248 void RenderManager::SetDefaultSurfaceOrientation( int orientation )
250 mImpl->defaultSurfaceOrientation = orientation;
253 void RenderManager::AddRenderer( OwnerPointer< Render::Renderer >& renderer )
255 // Initialize the renderer as we are now in render thread
256 renderer->Initialize( mImpl->context );
258 mImpl->rendererContainer.PushBack( renderer.Release() );
261 void RenderManager::RemoveRenderer( Render::Renderer* renderer )
263 mImpl->rendererContainer.EraseObject( renderer );
266 void RenderManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
268 mImpl->samplerContainer.PushBack( sampler.Release() );
271 void RenderManager::RemoveSampler( Render::Sampler* sampler )
273 mImpl->samplerContainer.EraseObject( sampler );
276 void RenderManager::AddTexture( OwnerPointer< Render::Texture >& texture )
278 texture->Initialize( mImpl->context );
279 mImpl->textureContainer.PushBack( texture.Release() );
282 void RenderManager::RemoveTexture( Render::Texture* texture )
284 DALI_ASSERT_DEBUG( NULL != texture );
286 // Find the texture, use reference to pointer so we can do the erase safely
287 for ( auto&& iter : mImpl->textureContainer )
289 if ( iter == texture )
291 texture->Destroy( mImpl->context );
292 mImpl->textureContainer.Erase( &iter ); // Texture found; now destroy it
298 void RenderManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
300 texture->Upload( mImpl->context, pixelData, params );
303 void RenderManager::GenerateMipmaps( Render::Texture* texture )
305 texture->GenerateMipmaps( mImpl->context );
308 void RenderManager::SetFilterMode( Render::Sampler* sampler, uint32_t minFilterMode, uint32_t magFilterMode )
310 sampler->mMinificationFilter = static_cast<Dali::FilterMode::Type>(minFilterMode);
311 sampler->mMagnificationFilter = static_cast<Dali::FilterMode::Type>(magFilterMode );
314 void RenderManager::SetWrapMode( Render::Sampler* sampler, uint32_t rWrapMode, uint32_t sWrapMode, uint32_t tWrapMode )
316 sampler->mRWrapMode = static_cast<Dali::WrapMode::Type>(rWrapMode);
317 sampler->mSWrapMode = static_cast<Dali::WrapMode::Type>(sWrapMode);
318 sampler->mTWrapMode = static_cast<Dali::WrapMode::Type>(tWrapMode);
321 void RenderManager::AddFrameBuffer( OwnerPointer< Render::FrameBuffer >& frameBuffer )
323 Render::FrameBuffer* frameBufferPtr = frameBuffer.Release();
324 mImpl->frameBufferContainer.PushBack( frameBufferPtr );
325 if ( frameBufferPtr->IsSurfaceBacked() )
327 frameBufferPtr->Initialize( *mImpl->CreateSurfaceContext() );
331 frameBufferPtr->Initialize( mImpl->context );
335 void RenderManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer )
337 DALI_ASSERT_DEBUG( NULL != frameBuffer );
339 // Find the sampler, use reference so we can safely do the erase
340 for ( auto&& iter : mImpl->frameBufferContainer )
342 if ( iter == frameBuffer )
344 frameBuffer->Destroy( mImpl->context );
346 if ( frameBuffer->IsSurfaceBacked() )
348 auto surfaceFrameBuffer = static_cast<Render::SurfaceFrameBuffer*>( frameBuffer );
349 mImpl->DestroySurfaceContext( surfaceFrameBuffer->GetContext() );
352 mImpl->frameBufferContainer.Erase( &iter ); // frameBuffer found; now destroy it
359 void RenderManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer )
361 if ( !frameBuffer->IsSurfaceBacked() )
363 auto textureFrameBuffer = static_cast<Render::TextureFrameBuffer*>( frameBuffer );
364 textureFrameBuffer->AttachColorTexture( mImpl->context, texture, mipmapLevel, layer );
368 void RenderManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
370 mImpl->propertyBufferContainer.PushBack( propertyBuffer.Release() );
373 void RenderManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
375 mImpl->propertyBufferContainer.EraseObject( propertyBuffer );
378 void RenderManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
380 propertyBuffer->SetFormat( format.Release() );
383 void RenderManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<uint8_t> >& data, uint32_t size )
385 propertyBuffer->SetData( data.Release(), size );
388 void RenderManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<uint16_t>& indices )
390 geometry->SetIndexBuffer( indices );
393 void RenderManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
395 mImpl->geometryContainer.PushBack( geometry.Release() );
398 void RenderManager::RemoveGeometry( Render::Geometry* geometry )
400 mImpl->geometryContainer.EraseObject( geometry );
403 void RenderManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
405 DALI_ASSERT_DEBUG( NULL != geometry );
408 for ( auto&& iter : mImpl->geometryContainer )
410 if ( iter == geometry )
412 iter->AddPropertyBuffer( propertyBuffer );
418 void RenderManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
420 DALI_ASSERT_DEBUG( NULL != geometry );
423 for ( auto&& iter : mImpl->geometryContainer )
425 if ( iter == geometry )
427 iter->RemovePropertyBuffer( propertyBuffer );
433 void RenderManager::SetGeometryType( Render::Geometry* geometry, uint32_t geometryType )
435 geometry->SetType( Render::Geometry::Type(geometryType) );
438 void RenderManager::AddRenderTracker( Render::RenderTracker* renderTracker )
440 mImpl->AddRenderTracker(renderTracker);
443 void RenderManager::RemoveRenderTracker( Render::RenderTracker* renderTracker )
445 mImpl->RemoveRenderTracker(renderTracker);
448 ProgramCache* RenderManager::GetProgramCache()
450 return &(mImpl->programController);
453 void RenderManager::Render( Integration::RenderStatus& status, bool forceClear )
455 DALI_PRINT_RENDER_START( mImpl->renderBufferIndex );
457 // Core::Render documents that GL context must be current before calling Render
458 DALI_ASSERT_DEBUG( mImpl->context.IsGlContextCreated() );
460 // Increment the frame count at the beginning of each frame
463 // Process messages queued during previous update
464 mImpl->renderQueue.ProcessMessages( mImpl->renderBufferIndex );
466 const uint32_t count = mImpl->instructions.Count( mImpl->renderBufferIndex );
467 const bool haveInstructions = count > 0u;
469 DALI_LOG_INFO( gLogFilter, Debug::General,
470 "Render: haveInstructions(%s) || mImpl->lastFrameWasRendered(%s) || forceClear(%s)\n",
471 haveInstructions ? "true" : "false",
472 mImpl->lastFrameWasRendered ? "true" : "false",
473 forceClear ? "true" : "false" );
475 // Only render if we have instructions to render, or the last frame was rendered (and therefore a clear is required).
476 if( haveInstructions || mImpl->lastFrameWasRendered || forceClear )
478 DALI_LOG_INFO( gLogFilter, Debug::General, "Render: Processing\n" );
480 // Mark that we will require a post-render step to be performed (includes swap-buffers).
481 status.SetNeedsPostRender( true );
483 // Switch to the shared context
484 if ( mImpl->currentContext != &mImpl->context )
486 mImpl->currentContext = &mImpl->context;
487 // Clear the current cached program when the context is switched
488 mImpl->programController.ClearCurrentProgram();
492 // Upload the geometries
493 for( uint32_t i = 0; i < count; ++i )
495 RenderInstruction& instruction = mImpl->instructions.At( mImpl->renderBufferIndex, i );
497 const Matrix* viewMatrix = instruction.GetViewMatrix( mImpl->renderBufferIndex );
498 const Matrix* projectionMatrix = instruction.GetProjectionMatrix( mImpl->renderBufferIndex );
500 DALI_ASSERT_DEBUG( viewMatrix );
501 DALI_ASSERT_DEBUG( projectionMatrix );
503 if( viewMatrix && projectionMatrix )
505 const RenderListContainer::SizeType renderListCount = instruction.RenderListCount();
507 // Iterate through each render list.
508 for( RenderListContainer::SizeType index = 0; index < renderListCount; ++index )
510 const RenderList* renderList = instruction.GetRenderList( index );
512 if( renderList && !renderList->IsEmpty() )
514 const std::size_t itemCount = renderList->Count();
515 for( uint32_t itemIndex = 0u; itemIndex < itemCount; ++itemIndex )
517 const RenderItem& item = renderList->GetItem( itemIndex );
518 if( DALI_LIKELY( item.mRenderer ) )
520 item.mRenderer->Upload( *mImpl->currentContext );
528 for( uint32_t i = 0; i < count; ++i )
530 RenderInstruction& instruction = mImpl->instructions.At( mImpl->renderBufferIndex, i );
532 DoRender( instruction );
535 GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
536 mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
537 for ( auto&& context : mImpl->surfaceContextContainer )
539 context->InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
542 //Notify RenderGeometries that rendering has finished
543 for ( auto&& iter : mImpl->geometryContainer )
545 iter->OnRenderFinished();
550 DALI_LOG_RELEASE_INFO( "RenderManager::Render: Skip rendering [%d, %d, %d]\n", haveInstructions, mImpl->lastFrameWasRendered, forceClear );
553 mImpl->UpdateTrackers();
555 // If this frame was rendered due to instructions existing, we mark this so we know to clear the next frame.
556 mImpl->lastFrameWasRendered = haveInstructions;
559 * The rendering has finished; swap to the next buffer.
560 * Ideally the update has just finished using this buffer; otherwise the render thread
561 * should block until the update has finished.
563 mImpl->renderBufferIndex = (0 != mImpl->renderBufferIndex) ? 0 : 1;
565 DALI_PRINT_RENDER_END();
568 void RenderManager::DoRender( RenderInstruction& instruction )
570 Rect<int32_t> viewportRect;
573 if ( instruction.mIsClearColorSet )
575 clearColor = instruction.mClearColor;
579 clearColor = Dali::RenderTask::DEFAULT_CLEAR_COLOR;
582 Rect<int32_t> surfaceRect = mImpl->defaultSurfaceRect;
583 int surfaceOrientation = mImpl->defaultSurfaceOrientation;
584 Vector4 backgroundColor = mImpl->backgroundColor;
585 Integration::DepthBufferAvailable depthBufferAvailable = mImpl->depthBufferAvailable;
586 Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable;
588 Render::SurfaceFrameBuffer* surfaceFrameBuffer = nullptr;
589 if ( instruction.mFrameBuffer != 0 )
591 if ( instruction.mFrameBuffer->IsSurfaceBacked() )
593 surfaceFrameBuffer = static_cast<Render::SurfaceFrameBuffer*>( instruction.mFrameBuffer );
595 if ( mImpl->currentContext->IsSurfacelessContextSupported() )
597 Context* surfaceContext = surfaceFrameBuffer->GetContext();
598 if ( mImpl->currentContext != surfaceContext )
600 // Switch the correct context if rendering to a surface
601 mImpl->currentContext = surfaceContext;
602 // Clear the current cached program when the context is switched
603 mImpl->programController.ClearCurrentProgram();
607 surfaceRect = Rect<int32_t>( 0, 0, static_cast<int32_t>( surfaceFrameBuffer->GetWidth() ), static_cast<int32_t>( surfaceFrameBuffer->GetHeight() ) );
608 backgroundColor = surfaceFrameBuffer->GetBackgroundColor();
612 // Switch to shared context for off-screen buffer
613 mImpl->currentContext = &mImpl->context;
617 DALI_ASSERT_DEBUG( mImpl->currentContext->IsGlContextCreated() );
619 // reset the program matrices for all programs once per frame
620 // this ensures we will set view and projection matrix once per program per camera
621 mImpl->programController.ResetProgramMatrices();
623 if( instruction.mFrameBuffer )
625 instruction.mFrameBuffer->Bind( *mImpl->currentContext );
629 mImpl->currentContext->BindFramebuffer( GL_FRAMEBUFFER, 0u );
632 if ( surfaceFrameBuffer )
634 mImpl->currentContext->Viewport( surfaceRect.x,
637 surfaceRect.height );
639 mImpl->currentContext->ClearColor( backgroundColor.r,
645 // Clear the entire color, depth and stencil buffers for the default framebuffer, if required.
646 // It is important to clear all 3 buffers when they are being used, for performance on deferred renderers
647 // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit",
648 // and then stall. That problem is only noticeable when rendering a large number of vertices per frame.
650 mImpl->currentContext->SetScissorTest( false );
652 GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
654 mImpl->currentContext->ColorMask( true );
656 if( depthBufferAvailable == Integration::DepthBufferAvailable::TRUE )
658 mImpl->currentContext->DepthMask( true );
659 clearMask |= GL_DEPTH_BUFFER_BIT;
662 if( stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE)
664 mImpl->currentContext->ClearStencil( 0 );
665 mImpl->currentContext->StencilMask( 0xFF ); // 8 bit stencil mask, all 1's
666 clearMask |= GL_STENCIL_BUFFER_BIT;
669 mImpl->currentContext->Clear( clearMask, Context::FORCE_CLEAR );
671 if( !instruction.mIgnoreRenderToFbo && ( instruction.mFrameBuffer != 0 ) )
673 if ( instruction.mFrameBuffer->IsSurfaceBacked() ) // Surface rendering
675 if ( instruction.mIsViewportSet )
677 // For glViewport the lower-left corner is (0,0)
678 // For glViewport the lower-left corner is (0,0)
679 const int32_t y = ( surfaceRect.height - instruction.mViewport.height ) - instruction.mViewport.y;
680 viewportRect.Set( instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height );
684 viewportRect = surfaceRect;
687 else // Offscreen buffer rendering
689 if ( instruction.mIsViewportSet )
691 // For glViewport the lower-left corner is (0,0)
692 const int32_t y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
693 viewportRect.Set( instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height );
697 viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
699 surfaceOrientation = 0;
702 else // No Offscreen frame buffer rendering
704 // Check whether a viewport is specified, otherwise the full surface size is used
705 if ( instruction.mFrameBuffer != 0 )
707 if ( instruction.mIsViewportSet )
709 // For glViewport the lower-left corner is (0,0)
710 const int32_t y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
711 viewportRect.Set( instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height );
715 viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
720 viewportRect = surfaceRect;
724 if ( surfaceOrientation == 90 || surfaceOrientation == 270 )
726 int temp = viewportRect.width;
727 viewportRect.width = viewportRect.height;
728 viewportRect.height = temp;
731 mImpl->currentContext->Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
733 if ( instruction.mIsClearColorSet )
735 mImpl->currentContext->ClearColor( clearColor.r,
740 // Clear the viewport area only
741 mImpl->currentContext->SetScissorTest( true );
742 mImpl->currentContext->Scissor( viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height );
743 mImpl->currentContext->ColorMask( true );
744 mImpl->currentContext->Clear( GL_COLOR_BUFFER_BIT , Context::CHECK_CACHED_VALUES );
745 mImpl->currentContext->SetScissorTest( false );
748 mImpl->renderAlgorithms.ProcessRenderInstruction(
750 *mImpl->currentContext,
751 mImpl->renderBufferIndex,
752 depthBufferAvailable,
753 stencilBufferAvailable,
754 surfaceOrientation );
756 if( instruction.mRenderTracker && ( instruction.mFrameBuffer != 0 ) )
758 // This will create a sync object every frame this render tracker
759 // is alive (though it should be now be created only for
760 // render-once render tasks)
761 instruction.mRenderTracker->CreateSyncObject( mImpl->glSyncAbstraction );
762 instruction.mRenderTracker = NULL; // Only create once.
765 if ( surfaceFrameBuffer )
767 surfaceFrameBuffer->PostRender();
771 } // namespace SceneGraph
773 } // namespace Internal