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 ),
48 mColor( Vector4::ZERO ),
52 mTextureSet( nullptr ),
59 RenderItem::~RenderItem() = default;
61 ClippingBox RenderItem::CalculateViewportSpaceAABB( const Vector3& size, const int viewportWidth, const int viewportHeight ) const
63 // Calculate extent vector of the AABB:
64 const float halfActorX = size.x * 0.5f;
65 const float halfActorY = size.y * 0.5f;
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 ) };
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] ) );
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 )
93 if( corners[i].x < corners[smallestX].x )
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 );
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 );
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 ) );
115 return ClippingBox( x, y, z - x, w - y );
118 void RenderItem::operator delete( void* ptr )
120 gRenderItemPool.Free( static_cast<RenderItem*>( ptr ) );
123 } // namespace SceneGraph
125 } // namespace Internal