Merge "Clean up the code to build successfully on macOS" into devel/master
[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   mColor( Vector4::ZERO ),
49   mSize(),
50   mRenderer( nullptr ),
51   mNode( nullptr ),
52   mTextureSet( nullptr ),
53   mDepthIndex( 0 ),
54   mIsOpaque( true ),
55   mIsUpdated( false )
56 {
57 }
58
59 RenderItem::~RenderItem() = default;
60
61 ClippingBox RenderItem::CalculateViewportSpaceAABB( const Vector3& size, const int viewportWidth, const int viewportHeight ) const
62 {
63   // Calculate extent vector of the AABB:
64   const float halfActorX = size.x * 0.5f;
65   const float halfActorY = size.y * 0.5f;
66
67   // To transform the actor bounds to screen-space, We do a fast, 2D version of a matrix multiply optimized for 2D quads.
68   // This reduces float multiplications from 64 (16 * 4) to 12 (4 * 3).
69   // We create an array of 4 corners and directly initialize the first 3 with the matrix multiplication result of the respective corner.
70   // This causes the construction of the vector arrays contents in-place for optimization.
71   // We place the coords into the array in clockwise order, so we know opposite corners are always i + 2 from corner i.
72   // We skip the 4th corner here as we can calculate that from the other 3, bypassing matrix multiplication.
73   // Note: The below transform methods use a fast (2D) matrix multiply (only 4 multiplications are done).
74   Vector2 corners[4]{ Transform2D( mModelViewMatrix, -halfActorX, -halfActorY ),
75                       Transform2D( mModelViewMatrix,  halfActorX, -halfActorY ),
76                       Transform2D( mModelViewMatrix,  halfActorX,  halfActorY ) };
77
78   // 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).
79   corners[3] = Vector2( corners[0] + ( corners[2] - corners[1] ) );
80
81   // Calculate the AABB:
82   // We use knowledge that opposite corners will be the max/min of each other. Doing this reduces the normal 12 branching comparisons to 3.
83   // The standard equivalent min/max code of the below would be:
84   //       Vector2 AABBmax( std::max( corners[0].x, std::max( corners[1].x, std::max( corners[3].x, corners[2].x ) ) ),
85   //                        std::max( corners[0].y, std::max( corners[1].y, std::max( corners[3].y, corners[2].y ) ) ) );
86   //       Vector2 AABBmin( std::min( corners[0].x, std::min( corners[1].x, std::min( corners[3].x, corners[2].x ) ) ),
87   //                        std::min( corners[0].y, std::min( corners[1].y, std::min( corners[3].y, corners[2].y ) ) ) );
88   unsigned int smallestX = 0u;
89   // Loop 3 times to find the index of the smallest X value.
90   // Note: We deliberately do NOT unroll the code here as this hampers the compilers output.
91   for( unsigned int i = 1u; i < 4u; ++i )
92   {
93     if( corners[i].x < corners[smallestX].x )
94     {
95       smallestX = i;
96     }
97   }
98
99   // As we are dealing with a rectangle, we can assume opposite corners are the largest.
100   // So without doing min/max branching, we can fetch the min/max values of all the remaining X/Y coords from this one index.
101   Vector4 aabb( corners[smallestX].x, corners[( smallestX + 3u ) % 4].y, corners[( smallestX + 2u ) % 4].x, corners[( smallestX + 1u ) % 4].y );
102
103   // Return the AABB in screen-space pixels (x, y, width, height).
104   // Note: This is a algebraic simplification of: ( viewport.x - aabb.width ) / 2 - ( ( aabb.width / 2 ) + aabb.x ) per axis.
105   Vector4 aabbInScreen( static_cast<float>( viewportWidth )  * 0.5f - aabb.z,
106                         static_cast<float>( viewportHeight ) * 0.5f - aabb.w,
107                         static_cast<float>( viewportWidth )  * 0.5f - aabb.x,
108                         static_cast<float>( viewportHeight ) * 0.5f - aabb.y );
109
110   int x = static_cast< int >( floor( aabbInScreen.x ) );
111   int y = static_cast< int >( floor( aabbInScreen.y ) );
112   int z = static_cast< int >( roundf( aabbInScreen.z ) );
113   int w = static_cast< int >( roundf( aabbInScreen.w ) );
114
115   return ClippingBox( x, y, z - x, w - y );
116 }
117
118 void RenderItem::operator delete( void* ptr )
119 {
120   gRenderItemPool.Free( static_cast<RenderItem*>( ptr ) );
121 }
122
123 } // namespace SceneGraph
124
125 } // namespace Internal
126
127 } // namespace Dali