DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
// Aligned by 16
- clippingRect = Rect<int>(16, 736, 64, 64); // in screen coordinates, includes 3 last frames updates
+ clippingRect = Rect<int>(16, 736, 48, 64); // in screen coordinates, includes 3 last frames updates
DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
application.RenderWithPartialUpdate(damagedRects, clippingRect);
DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
DALI_TEST_EQUALS(clippingRect.IsEmpty(), false, TEST_LOCATION);
DALI_TEST_EQUALS(clippingRect.IsValid(), true, TEST_LOCATION);
- DALI_TEST_EQUALS<Rect<int>>(clippingRect, Rect<int>(16, 736, 64, 64), TEST_LOCATION);
+ DALI_TEST_EQUALS<Rect<int>>(clippingRect, Rect<int>(16, 736, 48, 64), TEST_LOCATION);
application.RenderWithPartialUpdate(damagedRects, clippingRect);
DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+ // Should be no damage rects, nothing changed
damagedRects.clear();
+ application.SendNotification();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+ // Should be 1 damage rect due to change in size
+ damagedRects.clear();
+ actor.SetProperty(Actor::Property::SIZE, Vector3(26.0f, 26.0f, 0.0f));
+ application.SendNotification();
application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+ clippingRect = Rect<int>(16, 752, 32, 48); // new clipping rect size increased due to change in actor size
DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
application.RenderWithPartialUpdate(damagedRects, clippingRect);
DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
- Rect<int> clippingRect = Rect<int>(0, 496, 160, 320);
+ Rect<int> clippingRect = Rect<int>(32, 560, 96, 176);
DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
application.RenderWithPartialUpdate(damagedRects, clippingRect);
#define DALI_INTERNAL_SCENE_GRAPH_NODE_DATA_PROVIDER_H
/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
#include <dali/internal/render/data-providers/uniform-map-data-provider.h>
+#include <dali/public-api/math/matrix.h>
+#include <cstring>
namespace Dali
{
namespace Internal
{
+
namespace SceneGraph
{
+class Node;
+class Renderer;
+class TextureSet;
+
+/**
+ * Structure to store partial rendering cache data
+ */
+struct PartialRenderingCacheInfo
+{
+ Node* node{nullptr}; /// Node associated with the entry
+ const Renderer* renderer{nullptr}; /// Renderer object
+ const TextureSet* textureSet{nullptr}; /// TextureSet object
+ Matrix matrix{}; /// Model-view matrix
+ Vector4 color{}; /// Color
+ Vector3 size{}; /// Size
+ Vector3 updatedSize{}; /// Updated size
+ bool isOpaque{}; /// Opacity state
+ uint32_t depthIndex{0u}; /// Depth index
+};
+
+/**
+ * Structure contains partial rendering data used in order to determine
+ * whether anything has changed and node has to be updated
+ */
+struct PartialRenderingNodeData
+{
+ /**
+ * @brief Retrieves current PartialDataCacheInfo structure
+ * @return Current PartialDataCacheInfo structure
+ */
+ PartialRenderingCacheInfo& GetCurrentCacheInfo()
+ {
+ return mData[mCurrentIndex];
+ }
+
+ /**
+ * @brief Tests whether cache changed since last frame
+ * @return True if changed
+ */
+ bool IsUpdated()
+ {
+ return 0 != memcmp( &mData[0], &mData[1], sizeof(PartialRenderingCacheInfo) );
+ }
+
+ /**
+ * @brief Swaps cache buffers
+ */
+ void SwapBuffers()
+ {
+ mCurrentIndex = static_cast<uint8_t>((~mCurrentIndex) & 1);
+ }
+
+ PartialRenderingCacheInfo mData[2u]; /// Double-buffered data
+ uint8_t mCurrentIndex {0u}; /// Current buffer index
+};
+
+/**
+ * An interface to provide partial rendering data
+ */
+class PartialRenderingDataProvider
+{
+public:
+
+ /**
+ * Constructor
+ */
+ PartialRenderingDataProvider() = default;
+
+ /**
+ * Destructor
+ */
+ virtual ~PartialRenderingDataProvider() = default;
+
+ /**
+ * @brief Returns partial rendering data associated with the node.
+ * @return A valid pointer to the partial rendering data or nullptr
+ */
+ PartialRenderingNodeData& GetPartialRenderingData()
+ {
+ return mPartialRenderingData;
+ }
+
+protected:
+
+ PartialRenderingNodeData mPartialRenderingData;
+};
+
/**
* An interface to provide data for a Renderer
*/
-class NodeDataProvider : UniformMapDataProvider
+class NodeDataProvider : UniformMapDataProvider, public PartialRenderingDataProvider
{
public:
// Get the next free RenderItem.
RenderItem& item = renderList.GetNextFreeItem();
- item.mIsUpdated = (item.mNode != renderable.mNode);
- item.mNode = renderable.mNode;
+ // Get cached values
+ auto& partialRenderingData = node->GetPartialRenderingData();
- bool prevIsOpaque = item.mIsOpaque;
- item.mIsOpaque = (opacityType == Renderer::OPAQUE);
- item.mIsUpdated |= (prevIsOpaque != item.mIsOpaque);
+ auto& partialRenderingCacheInfo = node->GetPartialRenderingData().GetCurrentCacheInfo();
+
+ partialRenderingCacheInfo.node = node;
+ partialRenderingCacheInfo.isOpaque = (opacityType == Renderer::OPAQUE);
+ partialRenderingCacheInfo.renderer = renderable.mRenderer;
+ partialRenderingCacheInfo.color = renderable.mNode->GetColor(updateBufferIndex);
+ partialRenderingCacheInfo.depthIndex = renderable.mNode->GetDepthIndex();
+
+ if( renderable.mRenderer )
+ {
+ partialRenderingCacheInfo.textureSet = renderable.mRenderer->GetTextures();
+ }
- Vector4 prevColor = item.mColor;
+ item.mNode = renderable.mNode;
+ item.mIsOpaque = (opacityType == Renderer::OPAQUE);
item.mColor = renderable.mNode->GetColor(updateBufferIndex);
- item.mIsUpdated |= (prevColor != item.mColor);
- int prevDepthIndex = item.mDepthIndex;
item.mDepthIndex = 0;
if (!isLayer3d)
{
item.mDepthIndex = renderable.mNode->GetDepthIndex();
}
- Render::Renderer* prevRenderer = item.mRenderer;
if (DALI_LIKELY(renderable.mRenderer))
{
item.mRenderer = &renderable.mRenderer->GetRenderer();
- const void* prevTextureSet = item.mTextureSet;
item.mTextureSet = renderable.mRenderer->GetTextures();
- item.mIsUpdated |= (prevTextureSet != item.mTextureSet);
item.mDepthIndex += renderable.mRenderer->GetDepthIndex();
}
else
item.mRenderer = nullptr;
}
- item.mIsUpdated |= (prevDepthIndex != item.mDepthIndex);
- item.mIsUpdated |= (prevRenderer != item.mRenderer);
item.mIsUpdated |= isLayer3d;
- if (!item.mIsUpdated)
- {
- Matrix prevModelViewMatrix = item.mModelViewMatrix;
- Vector3 prevSize = item.mSize;
-
- // Save ModelView matrix onto the item.
- node->GetWorldMatrixAndSize( item.mModelMatrix, item.mSize );
- Matrix::Multiply( item.mModelViewMatrix, item.mModelMatrix, viewMatrix );
+ // Save ModelView matrix onto the item.
+ node->GetWorldMatrixAndSize( item.mModelMatrix, item.mSize );
+ Matrix::Multiply( item.mModelViewMatrix, item.mModelMatrix, viewMatrix );
- item.mIsUpdated = ((prevSize != item.mSize) || (item.mModelViewMatrix != prevModelViewMatrix));
- }
- else
- {
- // Save ModelView matrix onto the item.
- node->GetWorldMatrixAndSize( item.mModelMatrix, item.mSize );
- Matrix::Multiply( item.mModelViewMatrix, item.mModelMatrix, viewMatrix );
- }
+ partialRenderingCacheInfo.matrix = item.mModelViewMatrix;
+ partialRenderingCacheInfo.size = item.mSize;
- item.mUpdateSize = node->GetUpdateSizeHint();
if (item.mUpdateSize == Vector3::ZERO)
{
// RenderItem::CalculateViewportSpaceAABB cannot cope with z transform
item.mUpdateSize = item.mSize;
}
}
- }
+ partialRenderingCacheInfo.updatedSize = item.mUpdateSize;
+ item.mIsUpdated = partialRenderingData.IsUpdated() || item.mIsUpdated;
+ partialRenderingData.SwapBuffers();
+ }
node->SetCulled( updateBufferIndex, false );
}
else