2 * Copyright (c) 2018 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-item.h>
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>
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;
40 RenderItem* RenderItem::New()
42 return new ( gRenderItemPool.AllocateRaw() ) RenderItem();
45 RenderItem::RenderItem()
46 : mModelMatrix( false ),
47 mModelViewMatrix( false ),
55 mPartialUpdateEnabled( false )
59 RenderItem::~RenderItem()
64 ClippingBox RenderItem::CalculateViewportSpaceAABB( const int viewportWidth, const int viewportHeight, const bool useUpdateSizeHint ) const
66 // Calculate extent vector of the AABB:
69 if( useUpdateSizeHint )
71 halfActorX = mUpdateSizeHint.x * 0.5f;
72 halfActorY = mUpdateSizeHint.y * 0.5f;
76 halfActorX = mSize.x * 0.5f;
77 halfActorY = mSize.y * 0.5f;
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 ) };
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] ) );
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 )
107 if( corners[i].x < corners[smallestX].x )
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 );
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 );
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 ) );
129 return ClippingBox( x, y, z - x, w - y );
132 void RenderItem::operator delete( void* ptr )
134 gRenderItemPool.Free( static_cast<RenderItem*>( ptr ) );
138 } // namespace SceneGraph
140 } // namespace Internal