[Tizen] Implement partial update
[platform/core/uifw/dali-core.git] / dali / internal / render / common / render-item.cpp
1 /*
2  * Copyright (c) 2018 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-item.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/internal/common/memory-pool-object-allocator.h>
23 #include <dali/internal/render/renderers/render-renderer.h>
24 #include <dali/internal/common/math.h>
25
26 namespace
27 {
28 //Memory pool used to allocate new RenderItems. Memory used by this pool will be released when shutting down DALi
29 Dali::Internal::MemoryPoolObjectAllocator<Dali::Internal::SceneGraph::RenderItem> gRenderItemPool;
30 }
31 namespace Dali
32 {
33
34 namespace Internal
35 {
36
37 namespace SceneGraph
38 {
39
40 RenderItem* RenderItem::New()
41 {
42   return new ( gRenderItemPool.AllocateRaw() ) RenderItem();
43 }
44
45 RenderItem::RenderItem()
46 : mModelMatrix( false ),
47   mModelViewMatrix( false ),
48   mSize(),
49   mUpdateSizeHint(),
50   mRenderer( NULL ),
51   mNode( NULL ),
52   mTextureSet( NULL ),
53   mDepthIndex( 0 ),
54   mIsOpaque( true ),
55   mPartialUpdateEnabled( false )
56 {
57 }
58
59 RenderItem::~RenderItem()
60 {
61 }
62
63
64 ClippingBox RenderItem::CalculateViewportSpaceAABB( const int viewportWidth, const int viewportHeight, const bool useUpdateSizeHint ) const
65 {
66   // Calculate extent vector of the AABB:
67   float halfActorX;
68   float halfActorY;
69   if( useUpdateSizeHint )
70   {
71     halfActorX = mUpdateSizeHint.x * 0.5f;
72     halfActorY = mUpdateSizeHint.y * 0.5f;
73   }
74   else
75   {
76     halfActorX = mSize.x * 0.5f;
77     halfActorY = mSize.y * 0.5f;
78   }
79
80
81   // To transform the actor bounds to screen-space, We do a fast, 2D version of a matrix multiply optimized for 2D quads.
82   // This reduces float multiplications from 64 (16 * 4) to 12 (4 * 3).
83   // We create an array of 4 corners and directly initialize the first 3 with the matrix multiplication result of the respective corner.
84   // This causes the construction of the vector arrays contents in-place for optimization.
85   // We place the coords into the array in clockwise order, so we know opposite corners are always i + 2 from corner i.
86   // We skip the 4th corner here as we can calculate that from the other 3, bypassing matrix multiplication.
87   // Note: The below transform methods use a fast (2D) matrix multiply (only 4 multiplications are done).
88   Vector2 corners[4]{ Transform2D( mModelViewMatrix, -halfActorX, -halfActorY ),
89                       Transform2D( mModelViewMatrix,  halfActorX, -halfActorY ),
90                       Transform2D( mModelViewMatrix,  halfActorX,  halfActorY ) };
91
92   // As we are dealing with a rectangle, we can do a fast calculation to get the 4th corner from knowing the other 3 (even if rotated).
93   corners[3] = Vector2( corners[0] + ( corners[2] - corners[1] ) );
94
95   // Calculate the AABB:
96   // We use knowledge that opposite corners will be the max/min of each other. Doing this reduces the normal 12 branching comparisons to 3.
97   // The standard equivalent min/max code of the below would be:
98   //       Vector2 AABBmax( std::max( corners[0].x, std::max( corners[1].x, std::max( corners[3].x, corners[2].x ) ) ),
99   //                        std::max( corners[0].y, std::max( corners[1].y, std::max( corners[3].y, corners[2].y ) ) ) );
100   //       Vector2 AABBmin( std::min( corners[0].x, std::min( corners[1].x, std::min( corners[3].x, corners[2].x ) ) ),
101   //                        std::min( corners[0].y, std::min( corners[1].y, std::min( corners[3].y, corners[2].y ) ) ) );
102   unsigned int smallestX = 0u;
103   // Loop 3 times to find the index of the smallest X value.
104   // Note: We deliberately do NOT unroll the code here as this hampers the compilers output.
105   for( unsigned int i = 1u; i < 4u; ++i )
106   {
107     if( corners[i].x < corners[smallestX].x )
108     {
109       smallestX = i;
110     }
111   }
112
113   // As we are dealing with a rectangle, we can assume opposite corners are the largest.
114   // So without doing min/max branching, we can fetch the min/max values of all the remaining X/Y coords from this one index.
115   Vector4 aabb( corners[smallestX].x, corners[( smallestX + 3u ) % 4].y, corners[( smallestX + 2u ) % 4].x, corners[( smallestX + 1u ) % 4].y );
116
117   // Return the AABB in screen-space pixels (x, y, width, height).
118   // Note: This is a algebraic simplification of: ( viewport.x - aabb.width ) / 2 - ( ( aabb.width / 2 ) + aabb.x ) per axis.
119   Vector4 aabbInScreen( static_cast<float>( viewportWidth )  * 0.5f - aabb.z,
120                         static_cast<float>( viewportHeight ) * 0.5f - aabb.w,
121                         static_cast<float>( viewportWidth )  * 0.5f - aabb.x,
122                         static_cast<float>( viewportHeight ) * 0.5f - aabb.y );
123
124   int x = static_cast< int >( roundf( aabbInScreen.x ) );
125   int y = static_cast< int >( roundf( aabbInScreen.y ) );
126   int z = static_cast< int >( roundf( aabbInScreen.z ) );
127   int w = static_cast< int >( roundf( aabbInScreen.w ) );
128
129   return ClippingBox( x, y, z - x, w - y );
130 }
131
132 void RenderItem::operator delete( void* ptr )
133 {
134   gRenderItemPool.Free( static_cast<RenderItem*>( ptr ) );
135 }
136
137
138 } // namespace SceneGraph
139
140 } // namespace Internal
141
142 } // namespace Dali