Merge "Clean up the code to build successfully on macOS" into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / render / gl-resources / frame-buffer-state-cache.cpp
1 /*
2  * Copyright (c) 2019 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 "frame-buffer-state-cache.h"
20
21 // INTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <dali/integration-api/gl-defines.h>
24
25 namespace Dali
26 {
27
28 namespace
29 {
30
31 const uint32_t INITIAL_FRAMEBUFFER_STATE = 0u;
32
33 }
34
35 namespace Internal
36 {
37
38 FrameBufferStateCache::FrameBufferStateCache()
39 :mCurrentFrameBufferId(0)
40 {
41 }
42
43 FrameBufferStateCache::~FrameBufferStateCache() = default;
44
45 GLbitfield FrameBufferStateCache::GetClearMask( GLbitfield mask, bool forceClear, bool scissorTestEnabled )
46 {
47   if( scissorTestEnabled )
48   {
49     // don't do anything if scissor test is enabled, in the future we could
50     // potentially keep track of frame buffer size vs scissor test size to see if the entire
51     // buffer is cleared or not.
52     return mask;
53   }
54   FrameBufferState* state = GetFrameBufferState( mCurrentFrameBufferId );
55   if( !state )
56   {
57     DALI_LOG_ERROR("FrameBuffer not found %d \n", mCurrentFrameBufferId);
58     return mask;
59   }
60
61   // if we are forcing the clear operation, then just update the internal cached values
62   if( forceClear )
63   {
64     SetClearState( state, mask );
65     return mask;
66   }
67
68   // use the cached values
69   if( mask & GL_COLOR_BUFFER_BIT)
70   {
71     // check if color buffer is currently clean
72     if( state->mState & COLOR_BUFFER_CLEAN )
73     {
74       // remove clear color buffer flag from bitmask, no need to clear twice
75       mask&= ~GL_COLOR_BUFFER_BIT;
76     }
77   }
78   if( mask & GL_DEPTH_BUFFER_BIT)
79   {
80     // check if depth buffer is currently clean
81     if( state->mState & DEPTH_BUFFER_CLEAN )
82     {
83       // remove clear depth buffer flag from bitmask, no need to clear twice
84       mask&= ~GL_DEPTH_BUFFER_BIT;
85     }
86   }
87   if( mask & GL_STENCIL_BUFFER_BIT)
88   {
89     // check if stencil buffer is currently clean
90     if( state->mState & STENCIL_BUFFER_CLEAN )
91     {
92       // remove clear stencil buffer flag from bitmask, no need to clear twice
93
94       mask&= ~GL_STENCIL_BUFFER_BIT;
95     }
96   }
97
98   // set the clear state based, what's about to be cleared
99   SetClearState( state, mask );
100
101   return mask;
102 }
103
104 void FrameBufferStateCache::SetCurrentFrameBuffer( GLuint frameBufferId )
105 {
106   mCurrentFrameBufferId = frameBufferId;
107 }
108
109 void FrameBufferStateCache::FrameBuffersDeleted( GLsizei count, const GLuint* const frameBuffers )
110 {
111   for( GLsizei i = 0; i < count; ++i )
112   {
113     DeleteFrameBuffer( frameBuffers[i] );
114   }
115 }
116 void FrameBufferStateCache::FrameBuffersCreated( GLsizei count, const GLuint* const frameBuffers )
117 {
118   for( GLsizei i = 0; i < count; ++i )
119   {
120     // check the frame buffer doesn't exist already
121     GLuint id = frameBuffers[i];
122
123     FrameBufferState* state =  GetFrameBufferState( id );
124     if( state )
125     {
126       DALI_LOG_ERROR("FrameBuffer already exists%d \n", id );
127       // reset its state
128       state->mState = INITIAL_FRAMEBUFFER_STATE;
129       continue;
130     }
131
132     FrameBufferState newFrameBuffer( frameBuffers[i] );
133     mFrameBufferStates.PushBack( newFrameBuffer );
134   }
135 }
136
137 void FrameBufferStateCache::DrawOperation( bool colorBuffer, bool depthBuffer, bool stencilBuffer )
138 {
139   FrameBufferState* state = GetFrameBufferState( mCurrentFrameBufferId );
140   if( !state )
141   {
142     // an error will have already been logged by the clear operation
143     return;
144   }
145
146   if( colorBuffer )
147   {
148     // un-set the clean bit
149     state->mState &= ~COLOR_BUFFER_CLEAN;
150   }
151   if( depthBuffer )
152   {
153     // un-set the clean bit
154     state->mState &= ~DEPTH_BUFFER_CLEAN;
155   }
156   if( stencilBuffer )
157   {
158     // un-set the clean bit
159     state->mState &= ~STENCIL_BUFFER_CLEAN;
160   }
161
162 }
163
164 void FrameBufferStateCache::Reset()
165 {
166   mFrameBufferStates.Clear();
167
168   // create the default frame buffer
169   GLuint id = 0; // 0 == default frame buffer id
170   FrameBuffersCreated( 1, &id );
171 }
172
173 void FrameBufferStateCache::SetClearState( FrameBufferState* state, GLbitfield mask )
174 {
175   if( mask & GL_COLOR_BUFFER_BIT)
176   {
177     // set the color buffer to clean
178     state->mState |= COLOR_BUFFER_CLEAN;
179   }
180   if( mask & GL_DEPTH_BUFFER_BIT)
181   {
182     // set the depth buffer to clean
183     state->mState |= DEPTH_BUFFER_CLEAN;
184   }
185   if( mask & GL_STENCIL_BUFFER_BIT)
186   {
187     // set the stencil buffer to clean
188     state->mState |= STENCIL_BUFFER_CLEAN;
189   }
190 }
191
192 FrameBufferStateCache::FrameBufferState* FrameBufferStateCache::GetFrameBufferState(  GLuint frameBufferId )
193 {
194   for( FrameBufferStateVector::SizeType i = 0; i < mFrameBufferStates.Count(); ++i )
195   {
196     FrameBufferState& state = mFrameBufferStates[i];
197     if( state.mId == frameBufferId )
198     {
199       return &state;
200     }
201   }
202   return nullptr;
203 }
204
205 void FrameBufferStateCache::DeleteFrameBuffer( GLuint frameBufferId )
206 {
207   FrameBufferStateVector::Iterator iter = mFrameBufferStates.Begin();
208   FrameBufferStateVector::Iterator endIter = mFrameBufferStates.End();
209
210   for( ; iter != endIter ; ++iter )
211   {
212    if( (*iter).mId == frameBufferId )
213    {
214      mFrameBufferStates.Erase( iter);
215      return;
216    }
217  }
218  DALI_LOG_ERROR("FrameBuffer not found %d \n", frameBufferId);
219 }
220
221 } // namespace Internal
222
223 } // namespace Dali